#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <cstdio>
#include <cstdlib>
#include <vector>
#define MAXSIZE 1024
#include <bitset>
#define LEN 100
using namespace std;
/*
 *the first section to define 5 states to record the machine
 * */
const int SPACE = 0;//代表输入的是空格，换行
const int LETTER = 1;//input letter;
const int NUMBER = 2;//input number
const int BOUND = 3;//input bound symbol
const int OPREATION = 4 ;//input Opreation
/***=====================================***/

/*
 * define the file descripter
 * */
//read file
FILE *fp_source;
//to restory identifier
FILE *fp_identifier;
FILE *fp_symbol;
FILE *fp_Opreation;
FILE *fp_number;
FILE *fp_boundSymbol;

//a string to save the whole char of file but except sapce and carriage
string str;
//indexof_str to record the length of the str;
int indexof_str=0;
//the state of FA
int state;
//the datastruct of keyword
struct Keyword_st{
	string name;
	int value;
	int indexbegin;
	int indexend;
};
//存储关键字的数组
struct Keyword_st keyword_tb[MAXSIZE];
//to record the length of keyword_tb;
int indexofkeword_tb =0;
//the datastruct of identifier
struct Identifier_st{
	void *p;//存放该变量的存储地址的值作为内码值。
	string name;
	int value;
	int indexbegin;
	int indexend;

};
struct Identifier_st identifier_tb[MAXSIZE];
//to record the length of identifier_tb;
int indexofidentifier_tb =0;
//the datastruct of bound
struct Boundsymbol_st{
	string name;
	int value;
	int indexbegin;
	int indexend;
};
struct Boundsymbol_st boundsymbol_tb[MAXSIZE];
//to record the length of boundsymbol_tb;
int indexofboudsymbol_tb =0;
//the datastruct of Opreation
struct Opreation_st{
	string name;
	int value;
	int indexbegin;
	int indexend;

};
struct Opreation_st opreation_tb[MAXSIZE];
//to record the length of Opreation_tb;
int indexofOpreation_tb = 0;
struct Number_st{
	string name;//字面值
	int value;//二进制值
	int indexbegin;
	int indexend;

};
struct Number_st number_tb[MAXSIZE];

//to record the length of number_tb;
int indexofmuber_tb = 0;

//define the resvese table;

string Reserve_tb[LEN];
int Reserve_tbbegin = 3;
int Reserve_tbend = 20;

//to init the Reserve_tb;
void init_Reserve_tb(){
	Reserve_tb[3]="int";
	Reserve_tb[4]="char";
	Reserve_tb[5]="double";
	Reserve_tb[6]="float";
	Reserve_tb[7]="struct";
	Reserve_tb[8]="if";
	Reserve_tb[9]="else";
	Reserve_tb[10]="while";
	Reserve_tb[11]="do";
	Reserve_tb[12]="for";
	Reserve_tb[13]="return";
	Reserve_tb[14]="static";
	Reserve_tb[15]="void";
	Reserve_tb[16]="include";
	Reserve_tb[17]="stdio.h";
	Reserve_tb[18]="switch";
	Reserve_tb[19]="case";
	Reserve_tb[20]="break";
}


//define the tbale of bound symbol

string Bound_tb[LEN];
int Boundbegin = 60;
int Boundend = 66;
void init_BounSymbol(){
	Bound_tb[60]="(";
	Bound_tb[61]=")";
	Bound_tb[62]=",";
	Bound_tb[63]=";";
	Bound_tb[64]="#";
	Bound_tb[65]="{";
	Bound_tb[66]="}";
}


//define the table if Opreation 
string Opreation_tb[2*LEN];
int Opreationbegin=91;
int Opreationend=102;
void init_Opreation(){
	Opreation_tb[91]="+";
	Opreation_tb[92]="-";
	Opreation_tb[93]="*";
	Opreation_tb[94]="/";
	Opreation_tb[95]="%";
	Opreation_tb[96]=">";
	Opreation_tb[97]="<";
	Opreation_tb[98]=">=";
	Opreation_tb[99]="<=";
	Opreation_tb[100]="=";
	Opreation_tb[101]="==";
	Opreation_tb[102]="!=";
}
//to record a mark
string token;
int indexoftoken=0;
//contact the ch;
void contact(char ch){
	token+=ch;
	indexoftoken++;
}

//is Space or enter;
int isSpace(char ch){
	if(ch ==' '||ch=='\n') return 1;
	return 0;

}
//is a letter
int isLetter(char ch){
	if((ch>='a'&&ch<='z')||(ch>='A'&&ch<='Z')){
		return 1;
	}
	return 0;
}
//is a figure
int isFigure(char ch){
	if((ch>='0'&&ch<='9')) return 1;
	return 0;
}

char opt[9]={'+','-','*','/','&','>','<','=','!'};
int isOpt(char ch){
	for(int i = 0;i<9;i++){
		if(ch==opt[i]) return 1;
	}
	return 0;
}

char bos[7]={'(',')',',',';','#','{','}'};
int isBos(char ch){
	for(int i=0;i<7;i++){
		if(ch==bos[i]) return 1;
	}
	return 0;
}
//is a resverse
int isReserve(string token){
	for(int i = Reserve_tbbegin;i<=Reserve_tbend;i++){
		if(Reserve_tb[i]==token) return i;
	}
	return 0;
}
//is a identifier
int isIdentifier(string token){
	return 0;
}
//is a bound symbol;
int isBoundsymbol(string token){
	for(int i = Boundbegin;i<=Boundend;i++){
		if(Bound_tb[i]==token)
			return i;
	}
	return 0;
}
//is a opreation
int isOpreation(string token){
	for(int i=Opreationbegin;i<=Opreationend;i++){
		if(Opreation_tb[i]==token) return i;
	}
	return 0;

}


//add reserve to keyword_tb
void addKeyword(string token,int a,int b,int c){
	
	keyword_tb[indexofkeword_tb].name = token;

	keyword_tb[indexofkeword_tb].value = a;
	keyword_tb[indexofkeword_tb].indexbegin = b;
	keyword_tb[indexofkeword_tb].indexend = c;

	indexofkeword_tb++;	
}
//add bound symbol
void addBound(string token,int a,int b,int c){
	boundsymbol_tb[indexofboudsymbol_tb].name = token;
	boundsymbol_tb[indexofboudsymbol_tb].value = a;
	boundsymbol_tb[indexofboudsymbol_tb].indexbegin = b;
	boundsymbol_tb[indexofboudsymbol_tb].indexend = c;
	indexofboudsymbol_tb++;

}
//add Opreation;
void addOpreation(string token,int a,int b,int c){
	opreation_tb[indexofOpreation_tb].name = token;
	opreation_tb[indexofOpreation_tb].value = a;
	opreation_tb[indexofOpreation_tb].indexbegin = b;
	opreation_tb[indexofOpreation_tb].indexend = c;
	indexofOpreation_tb++;
}



//将字符串转换为数据类型；
int strToNumber(string token){
	char *ch = &token[0];
	int i = atoi(ch);

	return i;

}
//add number
void addNumber(string token,int a,int b){
	number_tb[indexofmuber_tb].name = token;
		
	number_tb[indexofmuber_tb].value = strToNumber(token);
	number_tb[indexofmuber_tb].indexbegin = a;
	number_tb[indexofmuber_tb].indexend = b;
	indexofmuber_tb++;
}

//add opreation
//add identifier
void addIdentifier(string token,int a,int b){
	identifier_tb[indexofidentifier_tb].name = token;
	identifier_tb[indexofidentifier_tb].p = &(identifier_tb[indexofidentifier_tb].name);
	//identifier_tb[indexofidentifier_tb].value=a;

	identifier_tb[indexofidentifier_tb].indexbegin = a;
	identifier_tb[indexofidentifier_tb].indexend = b;	
	indexofidentifier_tb++;
}


//open file
ofstream outKeyword;
ofstream outIdentifier;
ofstream outOpreation;
ofstream outBoundsymbol;
ofstream outNumber;

void file_open(){
	fp_source = fopen("../input/source.txt","r");
	outKeyword.open("../out/reserve.txt",fstream::app);
       	outIdentifier.open("../out/identifier.txt",fstream::app);
        outOpreation.open("../out/opreation.txt",fstream::app);
        outBoundsymbol.open("../out/boundsymbol.txt",fstream::app);
        outNumber.open("../out/number.txt",fstream::app);
}

void file_close(){
	fclose(fp_source);
	outKeyword.close();
	outIdentifier.close();
	outOpreation.close();
	outBoundsymbol.close();
	outNumber.close();

}

//open file error
void show_err(FILE *fp){
	if(fp==NULL){
		
		printf("Cant't open the file!\n");
		exit(EXIT_FAILURE);
	}
}




/*
 *initialize the all relvent set
 * */
void initAll(){
	init_Reserve_tb();
	init_BounSymbol();
	init_Opreation();
	file_open();
}

void read(){
	//get the first item of the file;
//	cout<<state<<endl;
	int value;
	char ch = getc(fp_source);
//	cout<<ch<<endl;
	if(isSpace(ch)) {state = SPACE;}
	else if(isLetter(ch)) {state = LETTER;}
	else if(isFigure(ch)) {state = NUMBER;}
	else if(isOpt(ch)) {state = OPREATION;}
	else if(isBos(ch)) {state = BOUND;}
//	cout<<state<<endl;
//	cout<<ch<<endl;
	char chSave;//used to record the char just read;
	while(ch!=EOF){
		chSave = ch;
		ch = getc(fp_source);
		switch(state){
			case LETTER:
				//contact the char to str
				contact(chSave);
				//if the ch is a letter;keep th state 
				if(isFigure(ch)||isLetter(ch)) state = LETTER;
				else if((!isFigure(ch))&&(!isLetter(ch))){//the next char not the figure or letter;
					str+=token;
					int markType = 0;
					//is reserve
					if((markType=isReserve(token))){
						//if it is the Reserve and add it to keyword_tb;
						addKeyword(token,markType,indexof_str,indexof_str+indexoftoken);
						indexof_str+=indexoftoken;
						//set the token "",and length =0;
						indexoftoken = 0;
						token = "";
					//	cout<<"add keyword success!"<<endl;
					}
					else
					{//is identifier;	
						addIdentifier(token,indexof_str,indexof_str+indexoftoken);
						indexof_str+=indexoftoken;
						indexoftoken = 0;
						token = "";
					//	cout<<"add identifier success"<<endl;
					}

					if(isSpace(ch)){state = SPACE;}
					else if(isFigure(ch)) {state = NUMBER;}
					else if(isOpt(ch)){state = OPREATION;}
					else if(isBos(ch)){state = BOUND;}
				}
				break;
			case NUMBER:
				contact(chSave);
				if(isFigure(ch)) state = NUMBER;
				else if(!isFigure(ch)) {
					str+=token;
					addNumber(token,indexof_str,indexof_str+indexoftoken);
					token="";
					indexoftoken = 0;
					if(isSpace(ch)){state = SPACE;}
                                        else if(isLetter(ch)) {state = LETTER;}
                                        else if(isOpt(ch)){state = OPREATION;}
                                        else if(isBos(ch)){state = BOUND;}

				}
				break;
			case SPACE:
				if(isLetter(ch)) {state = LETTER;}
				else if(isSpace(ch)){ state = SPACE;}
				else if(isFigure(ch)) {state = NUMBER;}
				else if(isOpt(ch)) {state = OPREATION;}
				else if(isBos(ch)) {state = BOUND;}
				break;
			case BOUND:
				contact(chSave);
				str+=token;
				value = isBoundsymbol(token);
				addBound(token,value,indexof_str,indexoftoken);
				token = "";
				indexoftoken=0;
				if(isSpace(ch)){
					state = SPACE;
				}else if(isLetter(ch)){
					state = LETTER;
				}else if(isFigure(ch)){
					state = NUMBER;
				}else if(isOpt(ch)){
					state = OPREATION;
				}else if(isBos(ch)){
					state = BOUND; 
				}
				break;
			case OPREATION:
				contact(chSave);
				if(isOpt(ch)) {state = OPREATION;}
				else if(!isOpt(ch)){
					str+=token;
					value=isOpreation(token);
					addOpreation(token,value,indexof_str,indexof_str+indexoftoken);
					token = "";
					indexoftoken = 0;
					if(isLetter(ch)) {state = LETTER;}
					else if(isSpace(ch)){ state = SPACE;}
					else if(isFigure(ch)) {state = NUMBER;}
					else if(isBos(ch)) {state = BOUND;}
					
				}
				break;
			default:
				cout<<"error"<<endl;
				break;
			
		}
	}
}
void show_keyword_tb(){
	for(int i=0;i<indexofkeword_tb;i++){
 	cout<<"<name:"<<keyword_tb[i].name;
        cout<<" value:"<<keyword_tb[i].value<<">"<<endl;
        cout<<keyword_tb[i].indexbegin<<endl;
        cout<<keyword_tb[i].indexend<<endl;}

}
void show_identifier_tb(){
	for(int i=0;i<indexofidentifier_tb;i++){
		cout<<identifier_tb[i].name<<endl;
		cout<<identifier_tb[i].value<<endl;
		cout<<identifier_tb[i].p<<endl;
		cout<<identifier_tb[i].indexbegin<<endl;
		cout<<identifier_tb[i].indexend<<endl;
		
	}

}

void show_boundsymbol_tb(){
	for(int i=0;i<indexofboudsymbol_tb;i++){
		cout<<boundsymbol_tb[i].name<<endl;
		cout<<boundsymbol_tb[i].value<<endl;
		cout<<boundsymbol_tb[i].indexbegin<<endl;
		cout<<boundsymbol_tb[i].indexend<<endl;
	
	}

}

void show_opreation_tb(){
	for(int i = 0;i<indexofOpreation_tb;i++){
	
		cout<<opreation_tb[i].name<<endl;
		cout<<opreation_tb[i].value<<endl;
		cout<<opreation_tb[i].indexbegin<<endl;
		cout<<opreation_tb[i].indexend<<endl;
	}
}


void show_number_tb(){
	for(int i =0;i<indexofmuber_tb;i++){
		cout<<number_tb[i].name<<endl;
		cout<<number_tb[i].value<<endl;
		cout<<number_tb[i].indexbegin<<endl;
		cout<<number_tb[i].indexend<<endl;
	}

}

void show_test(){

	cout<<"============keyworld begin=========="<<endl;
        show_keyword_tb();
        cout<<"============keyworld end============"<<endl;
        putchar('\n');
        putchar('\n');
        putchar('\n');

        cout<<"===========identifier begin========="<<endl;
        show_identifier_tb();
        cout<<"===========identifier end==========="<<endl;
        cout<<endl;
        cout<<endl;
        cout<<endl;
        cout<<"==========bound begin==============="<<endl;
        show_boundsymbol_tb();
        cout<<"==========bound end================="<<endl;
        cout<<endl;
        cout<<endl;
        cout<<endl;
        cout<<"==========opreation begin==========="<<endl;
        show_opreation_tb();
        cout<<"==========opreation end============="<<endl;
        putchar('\n');
        cout<<endl;
        cout<<endl;
        cout<<"==========number begin============="<<endl;
        show_number_tb();
        cout<<"==========number end==============="<<endl;


}
//============存储格式=======<单词类别,自身值>；
//将keywor写入keyword.txt
void writeKeyword(){
	for(int i = 0;i<indexofkeword_tb;i++){
		outKeyword<<"<  ,"<<keyword_tb[i].value<<">"<<endl;
		outKeyword<<flush;
	}

}
void writeIdentifier(){
	for(int i = 0;i<indexofidentifier_tb;i++){
		outIdentifier<<"<"<<1<<","<<identifier_tb[i].p<<">"<<endl;
		outIdentifier<<flush;
	}
}
void writeOpreation(){
	for(int i = 0;i<indexofOpreation_tb;i++){
		outOpreation<<"< ,"<<opreation_tb[i].value<<">"<<endl;
		outOpreation<<flush;
	}
}

void writeBound(){
	for(int i = 0;i<indexofboudsymbol_tb;i++){
		outBoundsymbol<<"< ,"<<boundsymbol_tb[i].value<<">"<<endl;
		outBoundsymbol<<flush;
	}

}

void writeNumber(){
	for(int i = 0;i<indexofmuber_tb;i++){
		outNumber<<"<2,"<<(bitset<8>)(number_tb[i].value)<<">"<<endl;
		outNumber<<flush;
	}
}


void write_all(){
	writeKeyword();
	writeIdentifier();
	writeOpreation();
	writeNumber();
	writeBound();
}
int main(){
	/*
	 *iniialization
	 *
	 * */

	initAll();
	read();
	write_all();
	file_close();

	//show_test();
	//cout<<str<<endl;


	return 0;
}






















